import redisHandle from './redisHandle'
import app from 'src/app'
import mongodbHandle from './mongodbHandle'
var ObjectId = require('mongodb').ObjectId;
// import { battleHandle } from 'js/handle/battleHandle';
import Random from 'js/core/random';
import utils from 'src/core/utils';
import * as schedule from 'node-schedule'
import * as moment from 'moment'
import configFile from '../config';
app.env = 'dev'
app.config = configFile['dev']

class CsBattleInfoModel {
    times: number
    end: boolean
    end1: boolean
    end2: boolean
    perHour: number
    perDay: number
    constructor(opts) {
        opts = opts || {}
        this.times = opts.times || 0
        this.end = opts.end || false
        this.end1 = opts.end1 || false
        this.end2 = opts.end2 || false
        this.perHour = opts.perHour || 0
        this.perDay = opts.perDay || 0
    }
}


class CrossServiceBattleHandle {
    maxLvlObject: Object
    startFlag: boolean
    constructor() {
        this.startFlag = false
    }
    start = async () => {
        setTimeout(async () => {
            console.log('跨服开始')
            await this.auto()
            console.log('跨服结束')
        }, 15 * 1000)
        schedule.scheduleJob('0 30 * * * *', async () => {
            console.log('跨服开始')
            await this.auto()
            console.log('跨服结束')
        });
        schedule.scheduleJob('0 0 23 * * *', async () => {
            mongodbHandle.csAarenaDao.remove({ time: { $lte: moment().add(-3, 'day').valueOf() } })
        })
    }
    getInfo = async (): Promise<CsBattleInfoModel> => {
        let data = await redisHandle.get(app.config.gameName + 'csBattleInfo')
        if (data) {
            let info = JSON.parse(data)
            let csBattleInfoModel = new CsBattleInfoModel(info)
            return csBattleInfoModel
        } else {
            return new CsBattleInfoModel({})
        }
    }
    setInfo = async (data: CsBattleInfoModel) => {
        await redisHandle.set(app.config.gameName + 'csBattleInfo', JSON.stringify(data))
    }
    addPlayer = async (pID, serverID) => {
        let info = await this.getInfo()
        serverID = Number(serverID)
        if (serverID > 1000) {
            serverID = serverID % 1000
        }
        let value = await this.getPlayerValueByPid(pID)
        let nowDay = moment().date();
        if (value) {
            let data = this.getPlayerInfo(value)
            this.setPlayerInfo(pID, nowDay, data.totalTimes, data.times, data.lvl, serverID)
        } else {
            this.setPlayerInfo(pID, nowDay, 0, 0, 0, serverID)
        }
    }
    setPlayerInfo(pID, day, totalTimes, times, lvl, serverID: number = 0) {
        let data = serverID * 10000000000 + totalTimes * 100000000 + times * 1000000 + lvl * 100 + day
        redisHandle.zadd(app.config.gameName + 'csBattleScore', data, pID)
    }

    getPlayerInfo(data) {
        data = Number(data)
        let serverID = Math.floor(data / 10000000000)
        let totalTimes = Math.floor(data % 10000000000 / 100000000)
        let times = Math.floor(data % 100000000 / 1000000)
        let lvl = Math.floor(data % 1000000 / 100)
        let day = Math.floor(data % 100)
        return { serverID, totalTimes, times, lvl, day }
    }

    getPlayerValueByPid = async (pid) => {
        let value = await redisHandle.zscore(app.config.gameName + 'csBattleScore', pid)
        return value
    }

    getOldPlayerInfo(data) {
        data = Number(data)
        let totalTimes = Math.floor(data / 100000000000)
        let times = Math.floor(data % 100000000000 / 1000000000)
        let maxLvl = Math.floor(data % 1000000000 / 10000000)
        let lvl = Math.floor(data % 10000000 / 100000)
        let day = Math.floor(data % 100000)
        return { totalTimes, times, lvl, day, maxLvl }
    }

    auto = async () => {
        let csBattleInfo = await this.getInfo()
        let hour = moment().hour()
        if (this.startFlag == true) {
            return
        }
        if (hour == 0) {
            csBattleInfo.end = false
            csBattleInfo.times = 1
            csBattleInfo.perHour = hour
        } else if (hour == 22 && csBattleInfo.end == false) {
            csBattleInfo.end = true
            await this.setInfo(csBattleInfo)
            console.log('跨服结算')
            await this.settlement()
            console.log('跨服结算完成')
            return
        } else if (hour > 22) {
            return
        } else if (csBattleInfo.perHour !== hour) {
            csBattleInfo.end = false
            csBattleInfo.times += 1
            csBattleInfo.perHour = hour
        } else {
            csBattleInfo.end = false
        }
        this.startFlag = true
        await this.setInfo(csBattleInfo)
        let zmembers = await redisHandle.zrangeWITHSCORES(app.config.gameName + 'csBattleScore', 0, -1)
        let nowDay = moment().date();
        if (zmembers) {
            console.log('跨服人数:' + zmembers.length / 2)
            if (csBattleInfo.perDay !== moment().startOf('day').valueOf()) { //初始化
                console.log("初始化")
                csBattleInfo.perDay = moment().startOf('day').valueOf()
                await this.setInfo(csBattleInfo)
                for (let i = 0; i < zmembers.length / 2; i++) {
                    let pid = zmembers[2 * i]
                    let value = zmembers[2 * i + 1]
                    let playerInfo = this.getPlayerInfo(value)
                    let playerData = await mongodbHandle.playerDao.findOne({ _id: ObjectId(pid) })
                    if (playerData && playerData.cheat == true) {
                        await redisHandle.zerm(app.config.gameName + 'csBattleScore', pid)
                        continue
                    } else {
                        await this.setPlayerInfo(pid, playerInfo.day, 0, 0, 0, playerInfo.serverID)
                    }
                }
            }
            let playDataByLvl = {}
            let playerDataArray = []
            for (let i = 0; i < zmembers.length / 2; i++) {
                if (i % 250 == 0) {
                }
                let pid = zmembers[2 * i]
                let playerValue = await this.getPlayerValueByPid(pid)  //zmembers[2 * i + 1]
                let playerInfo = this.getPlayerInfo(playerValue)

                if (Math.abs(nowDay - playerInfo.day) > 7 && Math.abs(nowDay - playerInfo.day) < 24) {
                    await redisHandle.zerm(app.config.gameName + 'csBattleScore', pid)
                    continue
                }


                if (csBattleInfo.times == playerInfo.times) {
                    if (!playDataByLvl[playerInfo.lvl]) {
                        playDataByLvl[playerInfo.lvl] = []
                    }
                    playDataByLvl[playerInfo.lvl].push({ pid, serverID: playerInfo.serverID, isBattle: false })
                    continue
                } else {
                    // if (csBattleInfo.times == 1 && playerInfo.times !== csBattleInfo.times) {
                    //     let day = playerInfo.day
                    //     if (playerInfo.day - nowDay > 20) {
                    //         day = nowDay
                    //     }
                    //     await this.setPlayerInfo(pid, day, 0, 0, 0, playerInfo.serverID)
                    //     playerInfo.lvl = 0
                    //     playerInfo.totalTimes = 0
                    //     playerInfo.times = csBattleInfo.times
                    // }
                    if (!playDataByLvl[playerInfo.lvl]) {
                        playDataByLvl[playerInfo.lvl] = []
                    }
                    playDataByLvl[playerInfo.lvl].push({ pid, serverID: playerInfo.serverID, isBattle: true })
                }
            }
            playerDataArray = Object.entries(playDataByLvl)
            playerDataArray.forEach(item => {
                item[0] = Number(item[0])
            })
            playerDataArray.sort((a1, a2) => {
                return a2[0] - a1[0]
            })
            for (let i = 0; i < playerDataArray.length; i++) {
                let d = playerDataArray[i]
                let lvl = Number(d[0])
                let lvl2 = Number(d[0])
                let pids = d[1]
                let pids2 = playDataByLvl[lvl2]
                for (let j = 0; j < pids.length; j++) {
                    let pid = pids[j].pid
                    let isBattle = pids[j].isBattle
                    if (isBattle == false) {
                        continue
                    }
                    let serverID = pids[j].serverID
                    let pid2
                    if (pids2.length >= 2) {
                        let index = Math.floor(Math.random() * pids2.length)
                        pid2 = pids2[index].pid
                        if (pid2 == pid) {
                            if (pids2[index + 1]) {
                                pid2 = pids2[index + 1].pid
                            } else if (pids2[index - 1]) {
                                pid2 = pids2[index - 1].pid
                            }
                        }
                    } else {
                        pids2 = null
                        let index = lvl - 1
                        while (index >= 0) {
                            if (playDataByLvl[index]) {
                                pids2 = playDataByLvl[index]
                                lvl2 = index
                                break
                            }
                            index -= 1
                        }
                        if (index < 0) {
                            index = lvl + 1
                            while (index <= 22) {
                                if (playDataByLvl[index]) {
                                    pids2 = playDataByLvl[index]
                                    lvl2 = index
                                    break
                                }
                                index += 1
                            }
                        }
                        if (pids2) {
                            pid2 = utils.getOneFromArray(pids2).pid
                        } else {
                            continue
                        }
                    }
                    await this.battle(csBattleInfo, pid, pid2, lvl, lvl2, serverID)
                }
            }
        }
        this.startFlag = false
    }

    battle = async (info: CsBattleInfoModel, pid1, pid2, lvl1, lvl2, serverID) => {
        // let player1 = await mongodbHandle.playerDao.findOne({ _id: ObjectId(pid1) })
        // let player2 = await mongodbHandle.playerDao.findOne({ _id: ObjectId(pid2) })
        // if (!player1 || !player2) {
        //     return
        // }
        // let playerData1 = playerHandle.initPlayer(player1.playerData, 0, false)
        // let playerData2 = playerHandle.initPlayer(player2.playerData, 0, false)
        // let p1 = playerHandle.getFightAttriTeam(playerData1, true, true)
        // let p2 = playerHandle.getFightAttriTeam(playerData2, true, true)
        // let p1str = JSON.stringify(p1)
        // let p2str = JSON.stringify(p2)
        // let random = new Random()
        // let seed = random.getSeed()
        // let value = await redisHandle.zscore(app.config.gameName + 'csBattleScore', pid1)
        // let playerInfo = this.getPlayerInfo(value)
        // let { result } = await battleHandle.start(p1, p2, seed, 2)
        // if (result) {
        //     playerInfo.lvl += 1
        // }
        // if (playerInfo.lvl > 22) {
        //     playerInfo.lvl == 22
        // }
        // this.setPlayerInfo(pid1, playerInfo.day, playerInfo.totalTimes + 1, info.times, playerInfo.lvl, serverID)
        // await mongodbHandle.csAarenaDao.newAndSave(player1.name, player2.name, pid1, pid2, p1str, p2str, lvl1, lvl2, player1.currentServerID, player2.currentServerID, result, seed, app.version)
        // return result
    }

    settlement = async () => {
        let zmembers = await redisHandle.zrangeWITHSCORES(app.config.gameName + 'csBattleScore', 0, -1)
        let dateStr = moment().format('MM-DD')
        if (zmembers) {
            console.log('跨服结算人数:' + zmembers.length / 2)
            for (let i = 0; i < zmembers.length / 2; i++) {
                if (i % 500 == 0) {
                    await utils.setTimeout(50)
                }
                let pid = zmembers[2 * i]
                let value = zmembers[2 * i + 1]
                let playerInfo = this.getPlayerInfo(value)
                let lvl = playerInfo.lvl
                if (lvl > 22) {
                    lvl = 22
                }
                let awardPoint = lvl + playerInfo.totalTimes
                let diamond = (lvl + playerInfo.totalTimes) * 5
                // await mongodbHandle.mailDao.newAndSave(pid, `${dateStr}跨服挑战赛结算通知:获得竞技点${awardPoint * 10},最高星级${playerInfo.lvl},进行挑战匹配${playerInfo.totalTimes}次`, null, diamond, 0, 0, awardPoint * 10)
                await this.setPlayerInfo(pid, playerInfo.day, 0, 0, lvl, playerInfo.serverID)
            }
        }
    }

}

let crossServiceBattleHandle = new CrossServiceBattleHandle()
export default crossServiceBattleHandle